home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DESDOS.ARJ / MAIN.C < prev    next >
C/C++ Source or Header  |  1992-05-15  |  4KB  |  214 lines

  1. /* Encrypt/decrypt command compatible with Sun's "des" command */
  2. #include <stdio.h>
  3. #ifdef MSDOS
  4. #include <mem.h>
  5. #include <io.h>
  6. #include <fcntl.h>
  7. #endif
  8.  
  9. char iv[8];    /* Initial vector for CBC mode */
  10. int block;
  11.  
  12. main(argc,argv)
  13. int argc;
  14. char *argv[];
  15. {
  16.     int c,cnt,encrypt,decrypt,hexflag;
  17.     register int i;
  18.     char key[8],tkey1[20],tkey2[20],*akey,*getpass();
  19.     extern char *optarg;
  20.  
  21. #ifdef MSDOS    /* suppress \n translation on stdio */
  22.     setmode(fileno(stdin),O_BINARY);
  23.     setmode(fileno(stdout),O_BINARY);
  24. #endif
  25.  
  26.     hexflag = block = encrypt = decrypt = 0;
  27.     akey = NULL;
  28.     while((c = getopt(argc,argv,"hedk:b")) != EOF){
  29.         switch(c){
  30.         case 'h':
  31.             hexflag++;
  32.             break;
  33.         case 'e':
  34.             encrypt++;
  35.             break;
  36.         case 'd':
  37.             decrypt++;
  38.             break;
  39.         case 'k':
  40.             akey = optarg;
  41.             break;
  42.         case 'b':
  43.             block++;
  44.             break;
  45.         }
  46.     }
  47.     if(encrypt == 0 && decrypt == 0){
  48.         fprintf(stderr,"Usage: des -e|-d [-h] [-k key]\n");
  49.         exit(2);
  50.     }
  51.     if(akey == NULL){
  52.         /* No key on command line, prompt for it */
  53.         memset(tkey1,0,sizeof(tkey1));
  54.         memset(tkey2,0,sizeof(tkey2));
  55.         for(;;){
  56.             akey = getpass("Enter key: ");
  57.             strncpy(tkey1,akey,sizeof(tkey1));
  58.             akey = getpass("Enter key again: ");
  59.             strncpy(tkey2,akey,sizeof(tkey2));
  60.             if(strncmp(tkey1,tkey2,sizeof(tkey1)) != 0){
  61.                 fprintf(stderr,"Key mistyped, try again\n");
  62.             } else
  63.                 break;
  64.         }
  65.         akey = tkey1;
  66.     }
  67.     if(hexflag){
  68.         for(i=0;i<16;i++){
  69.             if(htoa(akey[i]) == -1){
  70.                 fprintf(stderr,"Non-hex character in key\n");
  71.                 exit(1);
  72.             }
  73.         }
  74.         gethex(key,akey,8);
  75.     } else {
  76.         strncpy(key,akey,8);
  77.         /* Set up key, determine parity bit */
  78.         for(cnt = 0; cnt < 8; cnt++){
  79.             c = 0;
  80.             for(i=0;i<7;i++)
  81.                 if(key[cnt] & (1 << i))
  82.                     c++;
  83.             if((c & 1) == 0)
  84.                 key[cnt] |= 0x80;
  85.             else
  86.                 key[cnt] &= ~0x80;
  87.         }
  88.     }
  89.     /* Blot out original key */
  90.     i = strlen(akey);
  91.     i = (i < 8) ? i : 8;
  92.     memset(akey,0,i);
  93.  
  94.     desinit(0);
  95.     setkey(key);
  96.  
  97.     /* Initialize IV to all zeros */
  98.     memset(iv,0,8);
  99.  
  100.     if(encrypt){
  101.         doencrypt();
  102.     } else {
  103.         dodecrypt();
  104.     }
  105. }
  106. /* Encrypt standard input to standard output */
  107. doencrypt()
  108. {
  109.     char work[8],*cp,*cp1;
  110.     int cnt,i;
  111.  
  112.     for(;;){
  113.         if((cnt = fread(work,1,8,stdin)) != 8){
  114.             /* Put residual byte count in the last block.
  115.              * Note that garbage is left in the other bytes,
  116.              * if any; this is a feature, not a bug, since it'll
  117.              * be stripped out at decrypt time.
  118.              */
  119.             work[7] = cnt;
  120.         }
  121.         if(!block){
  122.             /* CBC mode; chain in last cipher word */
  123.             cp = work;
  124.             cp1 = iv;
  125.             for(i=8; i!=0; i--)
  126.                 *cp++ ^= *cp1++;
  127.         }
  128.         endes(work);    /* Encrypt block */
  129.         if(!block){    /* Save outgoing ciphertext for chain */
  130.             memcpy(iv,work,8);
  131.         }
  132.         fwrite(work,1,8,stdout);
  133.         if(cnt != 8)
  134.             break;
  135.     }
  136. }
  137. dodecrypt()
  138. {
  139.     char work[8],nwork[8],ivtmp[8],*cp,*cp1;
  140.     int cnt,i;
  141.  
  142.  
  143.     cnt = fread(work,1,8,stdin);    /* Prime the pump */
  144.     for(;;){
  145.         if(!block){    /* Save incoming ciphertext for chain */
  146.             memcpy(ivtmp,work,8);
  147.         }
  148.         dedes(work);
  149.         if(!block){    /* Unchain block, save ciphertext for next */
  150.             cp = work;
  151.             cp1 = iv;
  152.             for(i=8; i!=0; i--){
  153.                 *cp++ ^= *cp1++;
  154.             }
  155.             memcpy(iv,ivtmp,8);
  156.         }
  157.         /* Save buffer pending next read */
  158.         memcpy(nwork,work,8);
  159.         /* Try to read next block */
  160.         cnt = fread(work,1,8,stdin);
  161.         if(cnt != 8){    /* Can "only" be 0 if not 8 */
  162.             /* Prev block was last one, write appropriate number
  163.              * of bytes
  164.              */
  165.             cnt = nwork[7];
  166.             if(cnt < 0 || cnt > 7){
  167.                 fprintf(stderr,"Corrupted file or wrong key\n");
  168.             } else if(cnt != 0)
  169.                 fwrite(nwork,1,cnt,stdout);
  170.             exit(0);
  171.         } else {
  172.             /* Now okay to write previous buffer */
  173.             fwrite(nwork,1,8,stdout);
  174.         }
  175.  
  176.     }
  177. }
  178. /* Convert hex/ascii nybble to binary */
  179. int
  180. htoa(c)
  181. char c;
  182. {
  183.     if(c >= '0' && c <= '9')
  184.         return c - '0';
  185.     if(c >= 'a' && c <= 'f')
  186.         return 10 + c - 'a';
  187.     if(c >= 'A' && c <= 'F')
  188.         return 10 + c - 'A';
  189.     return -1;
  190. }
  191. /* Convert bytes from hex/ascii to binary */
  192. gethex(result,cp,cnt)
  193. register char *result;
  194. register char *cp;
  195. register int cnt;
  196. {
  197.     while(cnt-- != 0){
  198.         *result = htoa(*cp++) << 4;
  199.         *result++ |= htoa(*cp++);
  200.     }
  201. }
  202. #ifdef    DEBUG
  203. put8(cp)
  204. register char *cp;
  205. {
  206.     int i;
  207.  
  208.     for(i=0;i<8;i++){
  209.         fprintf(stderr,"%02x ",*cp++ & 0xff);
  210.     }
  211. }
  212. #endif
  213.  
  214.